package com.bes.bessdk.service.customerdial;

import static com.bes.bessdk.BesSdkConstants.BES_CONNECT_ERROR;
import static com.bes.bessdk.BesSdkConstants.BES_CONNECT_SUCCESS;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.CUSTOMER_DIAL_GET_FLASH_ADDRESS_RESULT;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.CUSTOMER_DIAL_GET_MTU;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.CUSTOMER_DIAL_GET_SCREEN_PARAMETER;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.CUSTOMER_DIAL_RECEIVE_ALL_ACK;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.CUSTOMER_DIAL_RECEIVE_ACK_RESULT;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.CUSTOMER_DIAL_RECEIVE_DATA_ERROR;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.CUSTOMER_DIAL_RECEIVE_LSAT_FLASH_ADDR;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.CUSTOMER_DIAL_SEND_DATA_OVER;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.CUSTOMER_DIAL_USE_TEST;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.MSG_CUSTOMER_DIAL_GET_FLASH_ADDR_TIME_OUT;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.MSG_CUSTOMER_DIAL_GET_MTU_TIME_OUT;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.MSG_CUSTOMER_DIAL_SEND_DATA;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.MSG_CUSTOMER_DIAL_WAIT_ACK_TIMEOUT;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.MSG_CUSTOMER_DIAL_WAIT_CONFIRM_ERROR_TIMEOUT;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.OP_TOTA_WRITE_FLASH_PROCESS;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.OP_TOTA_WRITE_FLASH_WHOLE_CHECK_RESULT_FAIL;
import static com.bes.bessdk.service.customerdial.CustomerDialConstants.OP_TOTA_WRITE_FLASH_WHOLE_CHECK_RESULT_OK;

import android.content.Context;
import android.os.Handler;
import android.os.Message;

import androidx.annotation.NonNull;

import com.bes.bessdk.BesSdkConstants;
import com.bes.bessdk.service.base.BesBaseService;
import com.bes.bessdk.service.base.BesServiceConfig;
import com.bes.bessdk.service.base.BesServiceListener;
import com.bes.bessdk.utils.ArrayUtil;
import com.bes.bessdk.utils.SPHelper;
import com.bes.sdk.device.HmDevice;
import com.bes.sdk.message.BaseMessage;
import com.bes.sdk.utils.DeviceProtocol;

public class CustomerDialService extends BesBaseService {

    long sppSendDataDelay = 0;
    int mMtu = 640 / 16 * 16;//根据协议mMtu必须是16的倍数

    boolean canSendData = true;
    int lastResult = 0;
    boolean beginLastCheck = false;

    public CustomerDialService(BesServiceConfig serviceConfig, BesServiceListener listener, Context context) {
        super(serviceConfig, listener, context);
//        //testaa
        if (CUSTOMER_DIAL_USE_TEST) {
            return;
        }
        startConnect(serviceConfig);
        boolean defaultinterval = (boolean) SPHelper.getPreference(mContext, BesSdkConstants.BES_default_INTERVAL, BesSdkConstants.BES_default_INTERVAL_VALUE);
        long sppdelay = Long.parseLong((String) SPHelper.getPreference(mContext,BesSdkConstants.BES_SPP_INTERVAL,"1000"));
        if (defaultinterval == false) {
            sppSendDataDelay = sppdelay;
//            sendDataDelay = sppdelay;
        }
    }

    @Override
    public void onStatusChanged(HmDevice device, int status, DeviceProtocol protocol) {
        super.onStatusChanged(device, status, protocol);
        if (status == BES_CONNECT_SUCCESS) {
            callBackStateChangedMessage(BES_CONNECT_SUCCESS, "");
        } else if (status == BES_CONNECT_ERROR) {
            callBackStateChangedMessage(BES_CONNECT_ERROR,"error");
        }
    }

    @Override
    public void callBackTotaConnectState(boolean state) {
        if (state == true) {
            try {
                Thread.sleep(100);
                sendData(CustomerDialCMD.getCurrentScreenParameterCmd());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        super.callBackTotaConnectState(state);
    }

    @Override
    public void onDataReceived(BaseMessage deviceMessage) {
        super.onDataReceived(deviceMessage);
        if (mConfig.getTotaConnect() && !totauccess) {
            return;
        }
        LOG(TAG, "receive decode:" + ArrayUtil.toHex((byte[]) deviceMessage.getMsgContent()));
//        callBackStateChangedMessage(CUSTOMER_DIAL_LOG_INFO, "receive:" + ArrayUtil.toHex((byte[]) deviceMessage.getMsgContent()));
        int result = CustomerDialCMD.receiveData((byte[]) deviceMessage.getMsgContent(), mContext);
        LOG(TAG, "result:" + result);
        LOG(TAG, "lastResult:" + lastResult);

        if (lastResult == 0 && result != CUSTOMER_DIAL_GET_MTU) {

            return;
        }
        if (result == CUSTOMER_DIAL_GET_FLASH_ADDRESS_RESULT) {
            besCustomerDialMsgHandler.removeMessages(MSG_CUSTOMER_DIAL_GET_FLASH_ADDR_TIME_OUT);
            if (lastResult != CUSTOMER_DIAL_GET_MTU) {
                LOG(TAG, "lastResult != CUSTOMER_DIAL_GET_MTU");
                return;
            }

            sendPacketData();
        } else if (result == CUSTOMER_DIAL_RECEIVE_ACK_RESULT) {
            LOG(TAG, "result:" + "result == CUSTOMER_DIAL_RECEIVE_ACK_RESULT");
            besCustomerDialMsgHandler.removeMessages(MSG_CUSTOMER_DIAL_WAIT_ACK_TIMEOUT);

            sendPacketData();
        } else if (result == CUSTOMER_DIAL_RECEIVE_ALL_ACK) {
            besCustomerDialMsgHandler.removeMessages(MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT);
            callBackStateChangedMessage(OP_TOTA_WRITE_FLASH_PROCESS, CustomerDialCMD.getCurProgress());
            sendData(CustomerDialCMD.getWholeDataCheckCmd());
        } else if (result == CUSTOMER_DIAL_SEND_DATA_OVER) {
            LOG(TAG, "result:" + "result == CUSTOMER_DIAL_SEND_DATA_OVER");
            callBackStateChangedMessage(OP_TOTA_WRITE_FLASH_PROCESS, CustomerDialCMD.getCurProgress());
            sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT, 5000);
        } else if (result == CUSTOMER_DIAL_GET_MTU) {
            besCustomerDialMsgHandler.removeMessages(MSG_CUSTOMER_DIAL_GET_MTU_TIME_OUT);
            if (lastResult != 0) {
                LOG(TAG, "lastResult != 0");
                return;
            }
            mMtu = CustomerDialCMD.getCurMtu();
            mMtu = mMtu / 16 * 16;

            sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_GET_FLASH_ADDR_TIME_OUT, 1000);
            sendData(CustomerDialCMD.getCurGetFlashAddrData());
        } else if (result == CUSTOMER_DIAL_RECEIVE_DATA_ERROR) {
            besCustomerDialMsgHandler.removeMessages(MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT);
            canSendData = false;

            sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_WAIT_CONFIRM_ERROR_TIMEOUT, 1000);
            sendData(CustomerDialCMD.getConfirmDataErrorCmd());
        } else if (result == CUSTOMER_DIAL_RECEIVE_LSAT_FLASH_ADDR) {
            besCustomerDialMsgHandler.removeMessages(MSG_CUSTOMER_DIAL_WAIT_CONFIRM_ERROR_TIMEOUT);

            canSendData = true;
            sendPacketData();
        } else if (result == OP_TOTA_WRITE_FLASH_WHOLE_CHECK_RESULT_OK) {
            if (beginLastCheck == false) {
                return;
            }
            beginLastCheck = false;
            besCustomerDialMsgHandler.removeMessages(MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT);
            callBackStateChangedMessage(OP_TOTA_WRITE_FLASH_WHOLE_CHECK_RESULT_OK, "");
            return;
        } else if (result == OP_TOTA_WRITE_FLASH_WHOLE_CHECK_RESULT_FAIL) {
            if (beginLastCheck == false) {
                return;
            }
            beginLastCheck = false;
            besCustomerDialMsgHandler.removeMessages(MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT);
            callBackStateChangedMessage(OP_TOTA_WRITE_FLASH_WHOLE_CHECK_RESULT_FAIL, "");
            return;
        } else if (result == CUSTOMER_DIAL_GET_SCREEN_PARAMETER) {
            return;
        }
        else {
            callBackStateChangedMessage(result, "");
        }
        if (result != 0) {
            lastResult = result;
        }
    }

    public void test() {
        int result = CustomerDialCMD.receiveData(new byte[]{0x00, 0x60}, mContext);
        if (result == CUSTOMER_DIAL_RECEIVE_ACK_RESULT) {
            LOG(TAG, "result:" + "result == CUSTOMER_DIAL_RECEIVE_ACK_RESULT");
            sendPacketData();
        } else if (result == CUSTOMER_DIAL_SEND_DATA_OVER) {
            LOG(TAG, "result:" + "result == CUSTOMER_DIAL_SEND_DATA_OVER");
            sendData(CustomerDialCMD.getWholeDataCheckCmd());
        }
    }

    public void startTransfer(byte[] oldData, byte[] data, int type, int isIncremental, byte[] param) {
        canSendData = true;
        lastResult = 0;
        beginLastCheck = false;
        //差分升级弃用
        sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_GET_MTU_TIME_OUT, 1000);
        sendData(CustomerDialCMD.getStartTransferCmd(null, data, type, isIncremental, param));

//        //testaa
        if (CUSTOMER_DIAL_USE_TEST) {
            sendPacketData();
        }
    }

    private byte[][] curData = new byte[0][];
    private long sendDataDelay = 6;
    private int curSendCount = 0;

    private void sendPacketData() {
        callBackStateChangedMessage(OP_TOTA_WRITE_FLASH_PROCESS, CustomerDialCMD.getCurProgress());
        curData = CustomerDialCMD.getSendPackageData();
        if (curData.length == 0) {
            beginLastCheck = true;
            sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT, 1000);
            callBackStateChangedMessage(OP_TOTA_WRITE_FLASH_PROCESS, CustomerDialCMD.getCurProgress());
            sendData(CustomerDialCMD.getWholeDataCheckCmd());
            return;
        }
        LOG(TAG, "sendPacketData curData:----" + curData.length);
        curSendCount = 0;
        sendDataDelay(sendDataDelay);
    }

    private void sendDataDelay(long millis) {
        LOG(TAG, "sendDataDelay-------");
        if (canSendData == false) {
            return;
        }
        sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_SEND_DATA, millis);
    }

    private Handler besCustomerDialMsgHandler = new Handler(mHandlerThread.getLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            LOG(TAG, "besCustomerDialMsgHandler-----");
            switch (msg.what) {
                case MSG_CUSTOMER_DIAL_SEND_DATA:
                    LOG(TAG, "besCustomerDialMsgHandler curSendCount:----" + curSendCount);
                    if (curSendCount == curData.length || canSendData == false) {
                        return;
                    }
                    byte[] data = curData[curSendCount];
                    boolean send = sendSppData(data);

                    //        //testaa
                    if (CUSTOMER_DIAL_USE_TEST) {
                        send = true;
                    }
                    LOG(TAG, "besCustomerDialMsgHandler send:----" + send);

                    if (send) {
                        curSendCount ++;
                    } else {
                        new Handler().post(new Runnable() {
                            @Override
                            public void run() {
                                sendDataDelay(sendDataDelay);
                            }
                        });
                        return;
                    }
                    if (curSendCount < curData.length) {
                        sendDataDelay(sendDataDelay);
                        return;
                    }
                    int result = CustomerDialCMD.resetAndCanSend();
                    if (result == 0) {
                        sendPacketData();
                    } else if (result == 1) {
                        LOG(TAG, "MSG_CUSTOMER_DIAL_WAIT_ACK_TIMEOUT-------------等待ack");

                        sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_WAIT_ACK_TIMEOUT, 1500);
                    }
//                    else if (result == 2) {
//                        sendData(CustomerDialCMD.getWholeDataCheckCmd());
//                    }
                    break;
                case MSG_CUSTOMER_DIAL_WAIT_ACK_TIMEOUT:
                    LOG(TAG, "besCustomerDialMsgHandler-----MSG_CUSTOMER_DIAL_WAIT_ACK_TIMEOUT");
                    CustomerDialCMD.resetSendPackageCount();
                    sendPacketData();

                    break;
                case MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT:
                    LOG(TAG, "besCustomerDialMsgHandler-----MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT");
                    sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_WAIT_OVER_TIMEOUT, 1000);
                    sendData(CustomerDialCMD.getWholeDataCheckCmd());
                    break;
                case MSG_CUSTOMER_DIAL_WAIT_CONFIRM_ERROR_TIMEOUT:
                    LOG(TAG, "besCustomerDialMsgHandler-----MSG_CUSTOMER_DIAL_WAIT_CONFIRM_ERROR_TIMEOUT");
                    sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_WAIT_CONFIRM_ERROR_TIMEOUT, 2000);
                    sendData(CustomerDialCMD.getConfirmDataErrorCmd());
                    break;
                case MSG_CUSTOMER_DIAL_GET_MTU_TIME_OUT:
                    sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_GET_MTU_TIME_OUT, 1000);
                    sendData(CustomerDialCMD.getCurrentMtuCmd());
                    break;
                case MSG_CUSTOMER_DIAL_GET_FLASH_ADDR_TIME_OUT:
                    sendDataDelay(besCustomerDialMsgHandler, MSG_CUSTOMER_DIAL_GET_FLASH_ADDR_TIME_OUT, 1000);
                    sendData(CustomerDialCMD.getCurGetFlashAddrData());
                    break;
                default:
                    break;
            }
        }
    };
}
